"""
图书馆案例

- 1. 数据库配置
    - 作者模型【一方】
    - 书籍模型【多方】
- 2. 添加测试数据
- 3. 添加作者、书籍
- 4. 删除作者、删除书籍
"""
from flask import Flask, render_template, request, redirect, flash
from flask_sqlalchemy import SQLAlchemy
from flask_wtf.csrf import CSRFProtect

app = Flask(__name__)

# 设置密钥
app.config["SECRET_KEY"] = "dsfsdfasdfa"

# 使用 CSRFProtect 保护 app
CSRFProtect(app)

# 1. 设置数据库的配置信息
# mysql://[用户名]:[密码]@[主机地址][端口号]/[数据库名]
app.config["SQLALCHEMY_DATABASE_URI"] = "mysql://root:123456@127.0.0.1:3306/library"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False

# 2. 创建 sqlalchemy 对象，关联app
db = SQLAlchemy(app)


# 3. 作者模型类
# 作者模型【一方】
class Author(db.Model):  # 默认表名为 student
    # 【主键】 参数1：表示 id 的类型；参数2：表示 id 的约束类型
    __tablename__ = "authors"  # 手动设置表名
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(32))

    # 关系属性
    # 查看作者名下的书籍：Author.books
    # 查看书籍背后的作者：Book.author
    books = db.relationship("Book", backref="author")


# 4. 书籍模型类
# 书籍模型【多方】
class Book(db.Model):  # 默认表名为 student
    # 【主键】 参数1：表示 id 的类型；参数2：表示 id 的约束类型
    __tablename__ = "books"  # 手动设置表名
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(32))

    # 建立外键
    author_id = db.Column(db.Integer, db.ForeignKey(Author.id))
    # 等价语句：author_id = db.Column(db.Integer, db.ForeignKey("authors.id"))


@app.route("/")
def show_index():
    # 1. 查询所有作者的信息
    authors = Author.query.all()

    # 2. 携带作者的信息，渲染页面
    response = render_template("Cdemo01_library.html", authors=authors)
    return response


"""
添加数据的逻辑

作者不存在，则添加数据
作者存在，书籍存在，不添加数据
作者存在，书籍不存在，添加数据

"""


# 添加书籍
@app.route("/add_data", methods=["POST", "GET"])
def add_data():
    # 1. 获取提交的数据
    author_name = request.form.get("author")
    book_name = request.form.get("book")

    # 判断输入的数据是否为空
    if not all([author_name, book_name]):
        flash("作者或书籍不能为空！")
        return redirect("/")

    # 2. 携带作者的信息，渲染页面
    author = Author.query.filter(Author.name == author_name).first()

    # 3.判断作者是否存在
    if author:
        # 4. 通过书籍名称查询书籍对象
        book = Book.query.filter(
            # 判断作者是否写过该书
            Book.name == book_name,
            Book.author_id == author.id,
        ).first()

        # 5. 判断书籍对象是否存在
        if book:
            flash(f"{author_name}已经写了《{book_name}》")
        else:
            # 创建书籍对象，添加到数据库
            book_adding = Book(name=book_name, author_id=author.id)
            db.session.add(book_adding)
            db.session.commit()
    else:
        # 创建作者对象，添加到数据库
        author_adding = Author(name=author_name)
        db.session.add(author_adding)
        db.session.commit()

        # 创建书籍对象，添加到数据库
        book_adding = Book(name=book_name, author_id=author_adding.id)
        db.session.add(book_adding)
        db.session.commit()

    return redirect("/")


# 删除书籍
@app.route("/del_data/<int:book_id>", methods=["POST", "GET"])
def del_data(book_id):
    # 根据书籍编号取出书籍对象
    book = Book.query.get(book_id)

    # 删除该书籍对象
    db.session.delete(book)
    db.session.commit()

    # 重定向到显示页面
    return redirect("/")


# 删除书籍
@app.route("/del_author/<int:author_id>", methods=["POST", "GET"])
def del_author(author_id):
    # 根据作者编号取出作者对象
    author = Author.query.get(author_id)

    # 删除作者名下所有书籍
    for book in author.books:
        db.session.delete(book)

    # 删除该作者对象
    db.session.delete(author)
    db.session.commit()

    # 重定向到显示页面
    return redirect("/")


if __name__ == "__main__":
    # 为了演示方便，先删除后创建
    # 创建数据库的表，创建的是继承自 db.Model 的表
    with app.app_context():
        # 删除所有继承自db.Model的表
        db.drop_all()
        # 创建所有继承自db.Model的表
        db.create_all()

        # 添加测试数据
        # 生成作者数据
        au1 = Author(name="金庸")
        au2 = Author(name="古龙")
        au3 = Author(name="莫言")

        # 把数据提交给用户会话
        db.session.add_all([au1, au2, au3])

        # 提交会话
        db.session.commit()

        # 生成书籍数据
        bk1 = Book(name="笑傲江湖", author_id=au1.id)
        bk2 = Book(name="神雕侠侣", author_id=au1.id)
        bk3 = Book(name="欢乐英雄", author_id=au2.id)
        bk4 = Book(name="白玉老虎", author_id=au2.id)
        bk5 = Book(name="丰乳肥臀", author_id=au3.id)
        bk6 = Book(name="红高粱家族", author_id=au3.id)

        # 把数据提交给用户会话
        db.session.add_all([bk1, bk2, bk3, bk4, bk5, bk6])

        # 提交会话
        db.session.commit()

    app.run(debug=True)
